package com.ilongsay.service.impl;

import com.ilongsay.dao.BillSqliteDao;
import com.ilongsay.dao.BillSqliteDetailDao;
import com.ilongsay.entity.ChaiFenSetting;
import com.ilongsay.entity.FaPiao;
import com.ilongsay.entity.FaPiaoDetail;
import com.ilongsay.service.IBillSqliteService;
import com.ilongsay.utils.CalcUtils;
import com.ilongsay.utils.ConfirmUtils;
import com.ilongsay.utils.DateUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * @Author ilongsay
 * @Email ilongsay@163.com
 * @Copyright 版本所有，侵权必究！
 * @Datetime 2018-11-13 23:04
 * @Describution
 */

@Service("billSqliteService")
public class BillSqliteServiceImpl implements IBillSqliteService {

    @Autowired
    private BillSqliteDao billSqliteDao;

    @Autowired
    private BillSqliteDetailDao billSqliteDetailDao;

    @Override
    public List<FaPiao> findBill() {
        //billSqliteDao.deleteDistincBill();
        List<FaPiao> bill = billSqliteDao.findBill();
        Collections.reverse(bill);//对list的元素进行倒序排列
        return bill;
    }

    /**
     * @param list
     * @return void
     *  批量插入数据，插入本地数据库的时候计算出汇总金额和税额
     */
    @Override
    public void insertBill(List<FaPiao> list) {

        //迭代数据批量插入到明细表，遍历每一条主表的信息
        for (FaPiao faPiao : list) {
            ConfirmUtils.confirmAmount(faPiao);
            faPiao.setUid(faPiao.getId().toString());
            for (FaPiaoDetail faPiaoDetail : faPiao.getFaPiaoDetails()) {
                faPiaoDetail.setUpid(faPiaoDetail.getPid().toString());//设置本地数据库的明细id
            }
            billSqliteDetailDao.insertBillDetail(faPiao.getFaPiaoDetails());
        }
        //数据批量插入到主表
        billSqliteDao.insertBill(list);
    }

    /**
     * @param faPiao
     * @return void
     * 测试单条数据插入
     */
    @Override
    public void insertBill1(FaPiao faPiao) {

        billSqliteDao.insertBill1(faPiao);
    }

    /**
     * @param newBillCode
     * @param oldBillCode
     * @return void
     * 更新订单信息
     */
    @Override
    public void updateBill(String newBillCode,String oldBillCode) {
        billSqliteDao.updateBill(newBillCode, oldBillCode);
    }

    /**
     * @param
     * @return void
     * 删除重复的订单数据，适用于客户在做完合并操作后，需要将重复的数据给删除
     */
    @Override
    public void deleteDinsticBill() {
        billSqliteDao.deleteDistincBill();
    }

    /**
     * @param list
     * @return void
     * 删除多个订单
     */
    @Override
    public void deleteBills(List<String> list) {
        billSqliteDao.deleteBillByParams(list);
        billSqliteDetailDao.deleteBillDetails(list);
        //billSqliteDao.deleteBDBill(list);
    }

    /**
     * @param oldBillCode
     * @return void
     * 将原始的订单号码的数据保存在数据库中，为之后的回写数据库表进行区分
     * XXX:日后需要完善一下代码
     */
    @Override
    public void addOldBillCode(String oldBillCode,String billCode) {
        billSqliteDao.addOldBillCode(oldBillCode,billCode);
    }

    /**
     * @param chaiFenSetting :拆分的设置
     * @return void
     * 单据拆分的业务逻辑的实现
     * //TODO:拆分的时候需要校验一下限额！如果拆分后超出了限额，那么还得继续按原来的规则进行拆分
     * //TODO：日后需要将这个拆分的服务给拆分
     * //XXX: 废弃不使用，已经整合到新的服务中！
     */
    @Override
    public void chaiFenBill(ChaiFenSetting chaiFenSetting) throws InvocationTargetException, IllegalAccessException{
        String[] split = chaiFenSetting.getBillCode().split("\\,");

        //按明细拆分订单号
        if (chaiFenSetting.getMingxi().equals("true") ) {

            String date = DateUtils.date().substring(8);
            List<String> list;
            //TODO：这里的时间需要改正一下
            String s = split[0] + "CF"+ date;
            String[] billCodeDetails = chaiFenSetting.getBillCodeDetail().split("\\,");
            //根据传进来的订单信息查询本地数据库的主表数据，有且仅有一条数据
            List<FaPiao> faPiaos = billSqliteDao.findBillByBillCode(split[0]);
            //在主表中插入多一条主表数据，名字为主表的订单号+CF
            faPiaos.get(0).setBillCode(s);
            //将数据插入到主表中
            billSqliteDao.insertBill(faPiaos);
            list = new ArrayList<>();
            for (String billCodeDetail : billCodeDetails) {
                list.add(billCodeDetail);
            }
            billSqliteDetailDao.updateByIds(list,s);

        } else {//除开明细拆分的话，就是按税率拆分

            //遍历传进来的拼接的单据
            for (String billCode : split) {
                //int i = 0;
                if (chaiFenSetting.getShuilv().equals("true")) {//如果税率勾选了，按税率拆分
                    //查询主表只有一条数据
                    List<FaPiao> faPiaos = billSqliteDao.findBillByBillCode(billCode);

                    //根据单号查询明细表
                    List<FaPiaoDetail> billCodes = billSqliteDetailDao.findBillDetailByBillCode(billCode);

                    Map<String,String> map = new HashMap<>();
                    for (FaPiaoDetail faPiaoDetail : billCodes) {
                        map.put(faPiaoDetail.getTaxRate(), faPiaoDetail.getTaxRate());
                    }
                    //这里需要进判断一下税率的个数，如果税率的个数只有1个就没必要进行拆分
                    for (String taxRate : map.keySet()) {
                        //i++;//每遍历一次i就+1，用来区分拆分单据，因为后缀是按税率，这里暂时取消
                        String bill = billCode + "CF" + taxRate;//拆分的后缀用税率表示，因为是按税率进行拆分的！
                        faPiaos.get(0).setBillCode(bill);//遍历一次就设置一次拆分后的订单号码
                        billSqliteDao.insertBill(faPiaos);//将新得到的拆分后的单据插入到主表数据中
                        billSqliteDetailDao.updateByTaxRates(taxRate, bill, billCode);
                    }
                    //删除原始的单据号，不是选择明细的拆分，不留原始单号！
                    billSqliteDao.deleteBillByBillCode(billCode);



                    //按金额拆分
                } else if (!chaiFenSetting.getAmount().equals("")&&!chaiFenSetting.getAmount().equals("0")) {//当拆分的金额不为空的时候！
                    //查询主表只有一条数据
                    List<FaPiao> faPiaos = billSqliteDao.findBillByBillCode(billCode);

                    //根据单号查询明细订单表
                    List<FaPiaoDetail> billCodes = billSqliteDetailDao.findBillDetailByBillCode(billCode);

                    double totalAmount = 0;//求出的总金额
                    double amount = Double.valueOf(chaiFenSetting.getAmount());//用户传进来的拆分金额
                    //得到明细的全部金额，若是主表有这个明细金额其实可以从主表中进行提取
                    for (FaPiaoDetail code : billCodes) {
                        totalAmount = CalcUtils.add(code.getTotal(),totalAmount);
                    }

                    int q = (int)totalAmount;
                    int m =  q % (int) amount==0 ? q/(int) amount : q/(int) amount+1;//拆分后单据的数量

                    List<List<FaPiaoDetail>> list1 = new LinkedList<>();
                    String getAmount = "0";
                    int loop2 = 0;
                    //制定循环的次数，能拆分多少单据便循环多少次
                    for (int i = 0; i < m; i++) {
                        List<FaPiaoDetail> list = new LinkedList<>();

                        loop2:for (int j = loop2; j < billCodes.size(); j++) {//遍历明细表的单据
                            loop2++;
                            FaPiaoDetail faPiaoDetail = billCodes.get(j);

                            getAmount = CalcUtils.add(faPiaoDetail.getTotal(), getAmount);

                            //如果小于明细的金额，就增加到list中
                            if(Double.valueOf(getAmount) <= amount){
                                list.add(faPiaoDetail);

                                //如果明细的金额大于设置金额，将明细的部分数据插入到新的list中
                            } else if (Double.valueOf(getAmount) > amount) {

                                String n = CalcUtils.sub(chaiFenSetting.getAmount(),CalcUtils.sub(getAmount,faPiaoDetail.getTotal()));
                                if (!n.equals("0")) {
                                    FaPiaoDetail faPiaoDetail2 = new FaPiaoDetail();
                                    //克隆一份对象，不然修改会改变list的引用的值
                                    BeanUtils.copyProperties(faPiaoDetail2, faPiaoDetail);

                                    faPiaoDetail2.setTotal(n);
                                    list.add(faPiaoDetail2);

                                    faPiaoDetail.setTotal(CalcUtils.sub(faPiaoDetail.getTotal(),n));
                                }
                                getAmount = "0";
                                loop2--;
                                break loop2;
                            }
                        }
                        //将得到的list集合插入到list中
                        list1.add(list);
                    }
                    //将符合数据的数据插入到明细表中
                    for (List<FaPiaoDetail> list : list1) {
                        billSqliteDao.deleteBillByBillCode(billCode);//将主表的原始单号删除
                        billSqliteDetailDao.deleteBillDetailsByBillCode(billCode);//将明细表的原始的数据删除
                        faPiaos.get(0).setBillCode(billCode+"000"+String.valueOf(m));//设置主表的订单号码
                        billSqliteDao.insertBill(faPiaos);//将主表插入到数据库中
                        for (FaPiaoDetail faPiaoDetail : list) {
                            faPiaoDetail.setBillCode(billCode+"000"+String.valueOf(m));
                        }
                        billSqliteDetailDao.insertBillDetailNoIds(list);//再将明细插入到数据库中
                        m--;
                    }

                }

            }
        }
    }
}
